<?php
/*
 * description：
 * author：wh
 * email：
 * createTime：{2020/6/2} {16:14}
 */

namespace wanghua\general_utility_tools_php\tool;

use FFMpeg\Coordinate\TimeCode;
use FFMpeg\FFMpeg;
use wanghua\general_utility_tools_php\tool\Tools;

/**
 * 视频处理工具
 *
 *     环境要求：
 *          PHP7.0+，ThinkPHP5.1+,linux ffmpeg插件安装最新版
 *
 *      配置参数：
 *          在config配置文件中
 *
 *
 * Class Video
 * @package libraries
 */
class Video
{
    private $config = [];
    public function __construct($config=[
        'ffmpeg.binaries' => '/usr/bin/ffmpeg',  // 或者其他FFmpeg实际路径
        'ffprobe.binaries' => '/usr/bin/ffprobe', // 或者其他ffprobe实际路径
    ])
    {
        $this->config = $config;
    }

    /**
     * desc：【不推荐】生成视频封面
     * 读取视频第一帧保存为图片
     * author：wh
     * @param $in_file 待处理视频路径（物理路径）
     * @param $out_file_name 缩略图文件名称(带后缀)
     * @param $path 指定存储路径
     * @return string
     */
    function createVideoImg($in_file, $out_file_name, $path=''){
        //缩略图保存路径
        $path = $path?$path:'/public/uploads/video_cover/'.date('Ymd').'/';
        $out_file = Tools::get_root_path().$path;

        if(!file_exists($out_file)){
            mkdir($out_file, 0777, true);
        }
        $out_file_path = $out_file.$out_file_name;
        //要执行的 cmd 命令
        //$cmd =  "ffmpeg -i ".$in_file." -y -f image2 -ss 2 -t 0.001 -s 350x240 ".$out_file;
        $cmd = "ffmpeg -i {$in_file} -f image2 -ss 2 -t 0.001 {$out_file_path}";
        $cmd = iconv('UTF-8','GB2312',$cmd);
        //执行命令
        exec($cmd);
        return $path.$out_file_name;
    }
    /**
     * desc：【不推荐】生成视频封面
     * 读取视频第一帧保存为图片
     * 注：仅适用于thinkPHP6
     * author：wh
     * @param $in_file 待处理视频路径
     * @param $out_file_name 缩略图文件名称
     * @return string
     */
    function toCreateVideoImg($in_file, $out_file_name, $path=''){
        //缩略图保存路径
        $path = $path?$path:'/static/upload/file/user_video_img/';
        $out_file = Tools::get_root_path().'public'.$path;

        if(!file_exists($out_file)){
            mkdir($out_file, 0777, true);
        }
        $out_file_path = $out_file.$out_file_name;
        //要执行的 cmd 命令
        //$cmd =  "ffmpeg -i ".$in_file." -y -f image2 -ss 2 -t 0.001 -s 350x240 ".$out_file;
        $cmd = "ffmpeg -i {$in_file} -f image2 -ss 2 -t 0.001 {$out_file_path}";
        $cmd = iconv('UTF-8','GB2312',$cmd);
        //执行命令
        exec($cmd);
        return $path.$out_file_name;
    }

    /**
     * desc：【推荐】创建视频封面
     * 依赖：
     *     composer require php-ffmpeg/php-ffmpeg
     *
     * 安装参考文章：
     * https://blog.csdn.net/qq_15941409/article/details/137846947?spm=1001.2014.3001.5501
     * author：wh
     * @param string $inputVideoPath 视频物理路径
     * @param string $out_file_name 带后缀的封面文件名
     * @param string $path 封面输出物理目录，不存在会自动创建目录
     * @return string
     */
    function createVideoCoverImage($inputVideoPath, $out_file_name='', $path=''){
        // 初始化FFMpeg实例，指向FFmpeg可执行文件的路径（根据实际情况调整路径）
        $ffmpeg = FFMpeg::create($this->config);
        // 指定输出图像文件的路径和格式（例如，输出为JPEG格式）
        $filename = $out_file_name?:Tools::rand_str(32) . '.jpg';
        $path = $path?:Tools::get_root_path() . 'public/uploads/video_cover/' .date('Ymd').'/';
        if(!file_exists($path)){
            mkdir($path, 0777, true);
        }
        $outputImage = $path. $filename;  // 替换为保存第一帧的路径
        // 打开视频文件
        $video = $ffmpeg->open($inputVideoPath);
        // 提取第一帧（默认情况下，FFMpeg库将从视频的开始处获取第一帧）
        $frame = $video->frame(TimeCode::fromSeconds(0));
        // 将第一帧保存到指定的图像文件
        $frame->save($outputImage, 'image/jpeg');
        return $outputImage;
    }

    /**
     * desc：视频文件（.m3u8格式）分片下载
     * author：wh
     * @param $local_file_path .m3u8格式本地文件路径
     * @param $download_fix_url 'v.f421220_0.ts'文件下载url前缀 eg:'https://v-tos-k.xiaoeknow.com/2919df88vodtranscq1252524126/4010c0b1387702307232915476/drm/'
     * @param string $save_path 保存路径
     */
    function videoDownloadM3u8($local_file_path,$download_fix_url,$save_path=''){
        set_time_limit(0);
        if($save_path && substr($save_path,-1)!='/'){//windows \ (不影响)
            $save_path.='/';
        }
        // cURL选项
        $curl = curl_init();


        // 设置连接超时时间（例如，300秒）
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 300);

        // 设置整个请求的超时时间（例如，3600秒，即1小时）
        curl_setopt($curl, CURLOPT_TIMEOUT, 3600);

        // 忽略信号引起的超时
        curl_setopt($curl, CURLOPT_NOSIGNAL, true);
        //$url = 'https://v-tos-k.xiaoeknow.com/2919df88vodtranscq1252524126/4010c0b1387702307232915476/drm/v.f421220.m3u8';
        // 保存.m3u8内容到临时文件
        //$tempM3u8File = 'D:\下载\myfile\v.f421220.m3u8';
        $tempM3u8File = $local_file_path;
        $m3u8Content = file_get_contents($tempM3u8File);
        // 读取.m3u8文件并获取所有.ts文件的URL
        $tsFiles = [];
        $lines = explode("\n", $m3u8Content);
        foreach ($lines as $line) {
            if (strpos($line, '.ts?') !== false) {
                $tsFiles[] = $line;
            }
        }

        // 下载所有.ts文件
        foreach ($tsFiles as $tsFile) {
            $url = $download_fix_url.$tsFile;
            //var_dump($url);die;
            //curl_setopt($curl, CURLOPT_URL, $tsFile);
            //设置抓取的url
            curl_setopt($curl, CURLOPT_URL, $url);
            $tsContent = curl_exec($curl);
            $tsFileName = $save_path.'video片段_' .time(). explode('?',$tsFile)[0];
            file_put_contents($tsFileName, $tsContent);
        }
    }
}